#!/usr/bin/env node
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

'use strict';

var program = require('commander');
var azureStorage = require('azure-storage');
var inputError = require('./common.js').inputError;
var serviceError = require('./common.js').serviceError;
var printSuccess = require('./common.js').printSuccess;
var getSas = require('./common.js').getSas;
var Registry = require('azure-iothub').Registry;

program
  .description('Import devices in bulk into the device identity registry. The input file gets uploaded to a blob and then an import job is started from that blob.')
  .usage('[options] --storage <storage-connection-string> --output <file-path>')
  .option('-i, --input <file-path>', 'path to the input file containing device descriptions')
  .option('-o, --output <file-path>', 'path indicating where to download the import log file generated by the service (empty in case of success)')
  .option('-s, --storage <storage-connection-string>', 'Azure blob storage connection string to be used during bulk import')
  .option('-l, --login <iothub-connection-string>', 'use the connection string provided as argument to use to authenticate with your IoT hub')
  .parse(process.argv);

if(!program.storage) inputError('A storage connection string with permissions to create a blob is required.');
if(!program.input) inputError('An input file path is required.');

var inputFile = program.input;
var outputFile = program.output;
var storageConnectionString = program.storage;
var sas = getSas(program.login);

var registry = Registry.fromSharedAccessSignature(sas);
var blobSvc = azureStorage.createBlobService(storageConnectionString);

var startDate = new Date();
var expiryDate = new Date(startDate);
// Use a large interval to account for clock errors and time to run the job.
expiryDate.setMinutes(startDate.getMinutes() + 100);
startDate.setMinutes(startDate.getMinutes() - 100);

var inputSharedAccessPolicy = {
  AccessPolicy: {
    Permissions: 'rl',
    Start: startDate,
    Expiry: expiryDate
  },
};

var outputSharedAccessPolicy = {
  AccessPolicy: {
    Permissions: 'rwd',
    Start: startDate,
    Expiry: expiryDate
  },
};

var inputContainerName = 'importcontainer';
var outputContainerName = 'exportcontainer';
var deviceFile = 'devices.txt';

blobSvc.createContainerIfNotExists(inputContainerName, function (error) {
  if(error) {
    serviceError('Could not create input container: ' + error.message);
  } else {
    var inputSasToken = blobSvc.generateSharedAccessSignature(inputContainerName, null, inputSharedAccessPolicy);
    var inputSasUrl = blobSvc.getUrl(inputContainerName, null, inputSasToken);
    blobSvc.createBlockBlobFromLocalFile(inputContainerName, deviceFile, inputFile, function (error) {
      if (error) {
        serviceError('Could not create import blob: ' + error.message);
      } else {
        blobSvc.createContainerIfNotExists(outputContainerName, function (error) {
          if (error) {
            serviceError('Could not create output container: ' + error.message);
          } else {
            var outputSasToken = blobSvc.generateSharedAccessSignature(outputContainerName, null, outputSharedAccessPolicy);
            var outputSasUrl = blobSvc.getUrl(outputContainerName, null, outputSasToken);
            registry.importDevicesFromBlob(inputSasUrl, outputSasUrl, function (error, result) {
              if (error) {
                serviceError('Could not start device import job: ' + error.message + ' : ' + error.responseBody);
              } else {
                var jobId = result.jobId;
                var interval = setInterval(function () {
                  registry.getJob(jobId, function (error, result) {
                    if (error) {
                      serviceError('Could not get import job status: ' + error.message + ' : ' + error.responseBody);
                    } else {
                      var status = result.status;
                      printSuccess('Job Id: '+ jobId + ': ' + status);
                      if (status === "completed") {
                        clearInterval(interval);
                        blobSvc.deleteBlob(inputContainerName, deviceFile, function(err){
                          if(err) {
                            serviceError('Could not erase import blob: ' + err.message);
                          } else {
                            printSuccess('Temporary import blob deleted.');
                          }
                        });
                        if(outputFile) {
                          blobSvc.getBlobToLocalFile(outputContainerName, 'importErrors.log', outputFile, function(err) {
                            if(err) {
                              serviceError('Could not download log file: ' + err.message);
                            } else {
                              printSuccess('Log file: ' + outputFile);
                            }
                          });
                        }
                      }
                    }
                  });
                }, 1000);
              }
            });
          }
        });
      }
    });
  }
});